// libyuv_test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <io.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <share.h>
#include <libyuv/convert.h>
#include <libyuv/convert_from.h>
#include <memory>
#include "YuvConverter.h"
#include <windows.h>

const int FRAME_WIDTH = 1280;
const int FRAME_HEIGHT = 720;

int _tmain(int argc, _TCHAR* argv[])
{
	int fd_in = -1, fd_out = -1;

	char pAppFilePath[_MAX_PATH] = { 0 };
	::GetModuleFileName(NULL, pAppFilePath, _MAX_PATH);
	if (strlen(pAppFilePath) > 0) {
		char* pSep = strrchr(pAppFilePath, '\\');
		if (pSep) {
			*++pSep = '\0';
		}
	}

	char pYuvFilePath[_MAX_PATH] = { 0 };
	sprintf_s(pYuvFilePath, "%stest-1280x720-i420-yu12.yuv", pAppFilePath);
	if (::GetFileAttributes(pYuvFilePath) == INVALID_FILE_ATTRIBUTES) {
		return -1;
	}

	errno_t err = _sopen_s(&fd_in, pYuvFilePath, _O_RDONLY | _O_BINARY, _SH_DENYNO, _S_IREAD | _S_IWRITE);
	_lseeki64(fd_in, 0, SEEK_END);
	__int64 file_size = _telli64(fd_in);
	_lseeki64(fd_in, 0, SEEK_SET);

	int frame_size_y = FRAME_WIDTH * FRAME_HEIGHT;
	int frame_size_uv = ((FRAME_WIDTH + 1) >> 1) * ((FRAME_HEIGHT + 1) >> 1);

	//For test, only read one frame, you can read all frames by frame_count
	//int frame_count = (int)(file_size / (frame_size_y + 2 * frame_size_uv));

	std::unique_ptr<uint8_t[]> y_buf, u_buf, v_buf;
	y_buf.reset(new uint8_t[frame_size_y]);
	u_buf.reset(new uint8_t[frame_size_uv]);
	v_buf.reset(new uint8_t[frame_size_uv]);

	_read(fd_in, y_buf.get(), frame_size_y);
	_read(fd_in, v_buf.get(), frame_size_uv);
	_read(fd_in, u_buf.get(), frame_size_uv);
	_close(fd_in);

	int stride_y = FRAME_WIDTH;
	int stride_u = (FRAME_WIDTH + 1) >> 1;
	int stride_v = (FRAME_WIDTH + 1) >> 1;

	int dst_buf_size = frame_size_y * 3;
	std::unique_ptr<uint8_t[]> dst_buf;
	dst_buf.reset(new uint8_t[dst_buf_size]);
	int dst_stride = FRAME_WIDTH * 3;

	//convert to RGB24 and save to .rgb file
	int ret = YuvConverter::I420ToRGB24(y_buf.get(), stride_y, u_buf.get(), stride_u, v_buf.get(), stride_v,
		dst_buf.get(), dst_stride, FRAME_WIDTH, FRAME_HEIGHT, YuvConverter::YU12);

	char pConvertFilePath[_MAX_PATH] = { 0 };
	sprintf_s(pConvertFilePath, "%stest-1280x720-i420-yu12.rgb", pAppFilePath);
	if (::GetFileAttributes(pConvertFilePath) != INVALID_FILE_ATTRIBUTES) {
		if (!::DeleteFile(pConvertFilePath)) {
			printf("Failed to delete the file");
			return -1;
		}
	}

	err = _sopen_s(&fd_out, pConvertFilePath,
		O_CREAT | O_WRONLY | _O_BINARY, _SH_DENYNO, 0);
	_write(fd_out, dst_buf.get(), dst_buf_size);
	_close(fd_out);

	return 0;
}

